package ar.edu.uba.fi.jmit.graphvisualizer.server.storage;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import ar.edu.uba.fi.jmit.graphvisualizer.server.ResourceProperties;

public class PairTimeStorage<T> {
	
	private long maxTime;
	
	private Map<Long, List<Pair<T>>> storedData;
	
	
	public PairTimeStorage() {
		this(Integer.valueOf(ResourceProperties.getProperty("jmit.graphvisualizer.defaultMonitorStorageTime")));
	}
	
	public PairTimeStorage(long time) {
		maxTime = time;
		storedData = Collections.synchronizedMap(new HashMap<Long, List<Pair<T>>>());
	}

	public void add(Date date, T data) {
		long mapKey = generateMapKey(date);
		List<Pair<T>> list = storedData.get(mapKey);
		if(list == null) {
			list = new LinkedList<Pair<T>>();
			storedData.put(mapKey, list);
		}
		list.add(new Pair<T>(data, date));
		Logger.getLogger(this.getClass()).debug("Adding data" + data + " of " + date);
		clearOldData();
		
	}
	
	private void clearOldData() {
		long firstKey = generateFirstMapKey();
		synchronized (storedData) {
			Collection<Long> allKeys = new LinkedList<Long>(storedData.keySet());
			for(long key:allKeys) {
				if(key < firstKey) {
					Logger.getLogger(this.getClass()).debug("Removing key " + key);
					storedData.remove(key);
				}
			}
		}
	}

	/**
	 * Returns the first map key to keep on the map
	 * @return
	 */
	private long generateFirstMapKey() {
		long now = generateMapKey(new Date());
		return now - maxTime;
	}

	private long generateMapKey(Date date) {
		return date.getTime() / 1000;
	}

	public List<Pair<T>> get() {
		clearOldData();
		List<Pair<T>> list = null;
		synchronized (storedData) {
			list = this.collect(storedData.values());
		}
		Collections.sort(list, new DateComparator());
		return list;
	}
	
	private class DateComparator implements Comparator<Pair<T>>{

		@Override
		public int compare(Pair<T> arg0, Pair<T> arg1) {
			return arg0.getDate().compareTo(arg1.getDate());
		}
		
	}

	private List<Pair<T>> collect(Collection<List<Pair<T>>> values) {
		List<Pair<T>> list = new LinkedList<Pair<T>>();
		for(List<Pair<T>> value:values) {
			list.addAll(value);
		}
		return list;
	}
}
